// i.d(t, { Z: () => RoomData })
import Data from "../object/Data"
import ObservableValue from "../observer/observable.value"
import Logger from "../utils/Logger"
import RoomValueMap from "../three/RoomValueMap"
const l = new Logger("room-data")
class Room {
  id: string
  meshGroup: number
  meshSubgroup: number
  floorId: string
  tags: any[]
  constructor(e: { id: string; meshGroup: number; meshSubgroup: number; floorId: string }) {
    this.tags = []
    e && Object.assign(this, e)
  }
}
interface RoomDataItem {
  boundingBox: THREE.Box3
  meshGroup: number
  parentMeshGroup: number
}
export default class RoomData extends Data {
  selected: ObservableValue<any>
  protected _rooms: Record<string, Room>
  floorToRoomsMap: Map<string, Room[]>
  constructor(e: Room) {
    super()
    this.name = "rooms"
    this.selected = new ObservableValue(null)
    this._rooms = {}
    this.floorToRoomsMap = new Map()
    if (e) for (const t of Object.values(e)) this.add(t)
  }
  mapMeshesToRooms(e: RoomValueMap<RoomDataItem>) {
    const t = new Set<string>()
    const i = new RoomValueMap<string>()
    for (const i of e) {
      const e = i.value.meshGroup
      const n = i.value.parentMeshGroup
      let s = this.getByMeshSubgroup(null === n ? -1 : n, e)
      const o = s?.id || String(e)
      t.add(o)
      if (!s) {
        l.debug(`Created non-existant Room for mesh subgroup ${e}`)
        s = new Room({
          id: o,
          meshGroup: null !== n ? n : void 0,
          meshSubgroup: e,
          floorId: String(n)
        })
        this.add(s)
      }
    }
    for (const e in this._rooms) {
      const n = this._rooms[e]
      t.has(e)
        ? i.set(n.meshGroup, n.meshSubgroup, n.id)
        : (l.debug(`Removing non-existant Room with mesh subgroup ${this._rooms[e].meshSubgroup}`), this.remove(e))
    }
    return i
  }
  add(e: Room) {
    this._rooms[e.id] = e
    const t = this.floorToRoomsMap.get(e.floorId)
    t ? t.push(e) : this.floorToRoomsMap.set(e.floorId, [e])
  }
  remove(e: string) {
    const t = this.get(e)
    if (!t) return
    const i = this.floorToRoomsMap.get(t.floorId)
    if (i) {
      const e = i.indexOf(t)
      e > -1 && i.splice(e, 1)
    }
    delete this._rooms[e]
  }
  rooms() {
    const e = this._rooms,
      t = Object.keys(this._rooms)
    return (function* () {
      for (const i of t) yield e[i]
    })()
  }
  get roomCount() {
    return Object.keys(this._rooms).length
  }
  get collection() {
    return this._rooms
  }
  get(e: string) {
    return this._rooms[e]
  }
  getByMeshSubgroup(e, t) {
    return Object.values(this._rooms).find(i => i.meshGroup === e && i.meshSubgroup === t)
  }
  roomsByFloor(e) {
    return this.floorToRoomsMap.get(e) || []
  }
}
